﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Configuration;
using System.Collections.ObjectModel;
using Framework.Constructor.Formularios;
using Framework.Constructor.Sql;

namespace Framework.Constructor
{
    public partial class frmDisenio : Form
    {
        #region Private Fields
        protected ConnectionStringSettings connectionStringSettings;
        protected BaseDeDatos baseDeDatos;
        protected Esquema esquema;
        protected Collection<Tabla> tablas;
        protected Collection<Vista> vistas;
        protected Collection<Procedimiento> procedimientos;
        protected Type tipo;
        protected ObjetoBase seleccionado;
        #endregion

        public frmDisenio()
        {
            InitializeComponent();
            this.FormLoad();
        }

        #region Cargar Controles
        private void CargarOrigenes()
        {
            cbOrigenes.Items.Clear();
            Collection<ConnectionStringSettings> conexiones = Configuracion.ObtenerOrigenes();
            foreach (ConnectionStringSettings conexion in conexiones)
            {
                cbOrigenes.Items.Add(conexion);
            }
            if (cbOrigenes.Items != null && cbOrigenes.Items.Count > 0)
                cbOrigenes.SelectedIndex = 0;
        }

        private void CargarBases()
        {
            cbBasesDeDatos.Items.Clear();
            Collection<BaseDeDatos> colleccion = Dao.ObtenerBases( this.connectionStringSettings );
            foreach ( BaseDeDatos item in colleccion )
            {
                cbBasesDeDatos.Items.Add( item );
            }
            if ( cbBasesDeDatos.Items.Count > 0 )
                cbBasesDeDatos.SelectedIndex = 0;
        }

        private void CargarEsquemas()
        {
            cbEsquemas.Items.Clear();
            Collection<Esquema> colleccion = Dao.ObtenerEsquemas( this.connectionStringSettings, this.baseDeDatos );
            foreach ( Esquema item in colleccion )
            {
                cbEsquemas.Items.Add( item );
            }
            if ( cbEsquemas.Items.Count > 0 )
                cbEsquemas.SelectedIndex = 0;
        }

        private void CargarObjetos()
        {
            tvBaseDatos.Nodes.Clear();
            if ( cbBasesDeDatos.SelectedItem != null )
            {
                this.tablas = Dao.ObtenerTablas( this.connectionStringSettings, this.baseDeDatos, this.esquema );
                this.vistas = Dao.ObtenerVistas( this.connectionStringSettings, this.baseDeDatos, this.esquema );
                this.procedimientos = Dao.ObtenerProcedimientos( this.connectionStringSettings, this.baseDeDatos, this.esquema );
            }
            TreeNode tnTablas = new TreeNode( "Tablas" );
            foreach ( Tabla item in this.tablas )
                tnTablas.Nodes.Add( item.Name );
            TreeNode tnVistas = new TreeNode( "Vistas" );
            foreach ( Vista item in this.vistas )
                tnVistas.Nodes.Add( item.Name );
            TreeNode tnProcedimientos = new TreeNode( "Procedimientos" );
            foreach ( Procedimiento item in this.procedimientos )
                tnProcedimientos.Nodes.Add( item.Name );
            tvBaseDatos.Nodes.Add( tnTablas );
            tvBaseDatos.Nodes.Add( tnVistas );
            tvBaseDatos.Nodes.Add( tnProcedimientos );
        }
        #endregion

        #region Habilitar Controles
        private void HabilitarControles()
        {
            this.HabilitarcbOrigenes();
            this.HabilitarBtnAddOrigen();
            this.HabilitarBtnDelOrigen();
            this.HabilitarcbBasesDeDatos();
            this.HabilitarBtnAddBaseDeDatos();
            this.HabilitarBtnDelBaseDeDatos();
            this.HabilitarcbEsquemas();
            this.HabilitarBtnAddEsquema();
            this.HabilitarBtnDelEsquema();

        }

        private void HabilitarcbOrigenes()
        {
            cbOrigenes.Enabled = cbOrigenes.Items.Count > 0;
        }

        private void HabilitarBtnAddOrigen()
        {
            btnAddOrigen.Enabled = true;
        }

        private void HabilitarBtnDelOrigen()
        {
            btnDelOrigen.Enabled = cbOrigenes.SelectedItem != null;
        }

        private void HabilitarcbBasesDeDatos()
        {
            if ( cbBasesDeDatos.Items.Count == 0 )
            {
                cbBasesDeDatos.Items.Add( "" );
                cbBasesDeDatos.SelectedIndex = 0;
                cbBasesDeDatos.Items.Clear();
            }
            cbBasesDeDatos.Enabled = cbBasesDeDatos.Items.Count > 0;
        }

        private void HabilitarBtnAddBaseDeDatos()
        {
            btnAddBaseDeDatos.Enabled = this.cbOrigenes.SelectedItem != null;
        }

        private void HabilitarBtnDelBaseDeDatos()
        {
            btnDelBaseDeDatos.Enabled = cbOrigenes.SelectedItem != null;
        }

        private void HabilitarcbEsquemas()
        {
            if ( cbEsquemas.Items.Count == 0 )
            {
                cbEsquemas.Items.Add( "" );
                cbEsquemas.SelectedIndex = 0;
                cbEsquemas.Items.Clear();
            }
            cbEsquemas.Enabled = cbEsquemas.Items.Count > 0;
        }

        private void HabilitarBtnAddEsquema()
        {
            btnAddEsquema.Enabled = this.cbBasesDeDatos.SelectedItem != null;
        }

        private void HabilitarBtnDelEsquema()
        {
            btnDelEsquema.Enabled = cbEsquemas.SelectedItem != null;
        }
        #endregion

        #region Eventos Controles
        private void btnAddOrigen_Click(object sender, EventArgs e)
        {
            frmConnectionStringBuilder frmConnexion = new frmConnectionStringBuilder();
            ConnectionStringSettings conexion = frmConnexion.Obtener();
            if (conexion != null)
                this.AgregarConexion(conexion);
        }

        private void btnDelOrigen_Click(object sender, EventArgs e)
        {
            Configuracion.BorrarOrigen(this.connectionStringSettings.Name);
            this.CargarOrigenes();
        }

        private void cbOrigenes_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.connectionStringSettings = (ConnectionStringSettings)cbOrigenes.SelectedItem;
            this.CargarBases();
            this.HabilitarControles();
        }

        private void cbBaseDeDatos_SelectedIndexChanged( object sender, EventArgs e )
        {
            if ( typeof( BaseDeDatos ) == cbBasesDeDatos.SelectedItem.GetType() )
            {
                this.baseDeDatos = (BaseDeDatos)cbBasesDeDatos.SelectedItem;
                this.CargarEsquemas();
                this.HabilitarControles();
            }
        }

        private void cbEsquemas_SelectedIndexChanged( object sender, EventArgs e )
        {
            if ( typeof( Esquema ) == cbEsquemas.SelectedItem.GetType() )
            {
                this.esquema = (Esquema)cbEsquemas.SelectedItem;
                this.CargarObjetos();
                this.HabilitarControles();
            }
        }

        private void tvBaseDatos_NodeMouseDoubleClick( object sender, TreeNodeMouseClickEventArgs e )
        {
            if ( tvBaseDatos.SelectedNode != null )
            {
                String objetoSeleccionado = tvBaseDatos.SelectedNode.Text;
                if ( tvBaseDatos.SelectedNode.Parent != null )
                {
                    String tipoSeleccionado = tvBaseDatos.SelectedNode.Parent.Text;
                    Int32 objetoId = 0;
                    switch ( tipoSeleccionado )
                    {
                        case "Tablas":
                            ObtenerDefinicionDeLaTabla( objetoSeleccionado );
                            this.tipo = typeof( Tabla );
                            break;
                        case "Vistas":
                            ObtenerDefinicionDeLaVista( objetoSeleccionado );
                            this.tipo = typeof( Vista );
                            break;
                        case "Procedimientos":
                            ObtenerSourceDelProcedimiento( objetoSeleccionado );
                            this.tipo = typeof( Procedimiento );
                            break;
                    }
                    KeyValuePair<String, String> conf = ObtenerConfigKeyValue();
                    String help = String.Format( "\t<add key =\"{0}\" value=\"{1}\"/>", conf.Key, conf.Value );
                    txtAppHelper.Text = String.Format( "<appSettings>{0}{1}{2}</appSettings>", Environment.NewLine, help, Environment.NewLine );
                }
            }
        }

        private void ObtenerDefinicionDeLaTabla( String objetoSeleccionado )
        {
            Int32 objetoId = 0;
            foreach ( Tabla item in this.tablas )
            {
                if ( item.Name.ToLowerInvariant() == objetoSeleccionado.ToLowerInvariant() )
                {
                    this.seleccionado = item;
                    txtDefinicion.Text = item.ToXmlString("");
                    break;
                }
            }
        }

        private void ObtenerDefinicionDeLaVista( String objetoSeleccionado)
        {
            Int32 objetoId = 0;
            foreach ( Vista item in this.vistas )
            {
                if ( item.Name.ToLowerInvariant() == objetoSeleccionado.ToLowerInvariant() )
                {
                    this.seleccionado = item;
                    objetoId = item.Id;
                    break;
                }
            }
        }

        private void ObtenerSourceDelProcedimiento( String objetoSeleccionado )
        {
            foreach ( Procedimiento item in this.procedimientos )
            {
                if ( item.Name.ToLowerInvariant() == objetoSeleccionado.ToLowerInvariant() )
                {
                    this.seleccionado = item;
                    String definicion = Dao.ObtenerDefinicionDelObjeto( this.connectionStringSettings, this.baseDeDatos, item.Id );
                    if ( definicion != null )
                        this.txtDefinicion.Text = definicion;
                    break;
                }
            }
        }

        private void btnGuardar_Click( object sender, EventArgs e )
        {
            Configuracion.GuardarConfiguracion( ObtenerConfigKeyValue() );
        }

        private KeyValuePair<String, String> ObtenerConfigKeyValue()
        {
            String valor = String.Format( "{0};{1};{2};{3};{4};", this.connectionStringSettings.Name, this.baseDeDatos.Name, this.esquema.Name, this.tipo.Name, this.seleccionado.Name );
            String key = String.Format( "{0}_{1}", "Objeto", this.seleccionado.Name );
            KeyValuePair<String, String> resultado = new KeyValuePair<string, string>( key, valor );
            return resultado;
        }
        #endregion

        #region Private Methods
        private void CargarControles()
        {
            this.CargarOrigenes();
        }

        private void FormLoad()
        {
            this.CargarControles();

            this.HabilitarControles();
        }

        private void AgregarConexion( ConnectionStringSettings connectionStringSettings )
        {
            Configuracion.GuardarOrigen( connectionStringSettings );
            this.SeleccionarOrigen( connectionStringSettings );
        }

        private void SeleccionarOrigen( ConnectionStringSettings connectionStringSettings )
        {
            this.CargarOrigenes();
            this.connectionStringSettings = connectionStringSettings;
            this.cbOrigenes.SelectedItem = this.connectionStringSettings;
        }
        #endregion
    }
}
